let wid = 0;
class Watcher {
  constructor(vm, exp, cb, options) {
    this.vm = vm;
    this.exp = exp;
    this.cb = cb;
    this.options = options;
    this.lazy = options.lazy;
    this.user = options.user;
    this.dirty = this.lazy;
    this.depsId = new Set();
    this.deps = [];
    if (typeof exp == "function") {
      this.getter = exp;
    } else {
      this.getter = function () {
        let path = this.exp.split(".");
        let obj = vm;
        for (let i = 0; i < path.length; i++) {
          obj = obj[path[i]];
        }
        return obj;
      };
    }
    this.value = this.lazy ? void 0 : this.get();
  }
  get() {
    pushTarget(this);
    let value = this.user ? this.getter() : this.getter.call(this.vm);
    popTarget();
    return value;
  }
  addDep(dep) {
    let id = dep.id;
    if (!this.depsId.has(id)) {
      // 收集dep
      this.deps.push(dep);
      // 保存dep的id
      this.depsId.add(id);
      dep.addSub(this);
    }
  }
  run() {
    let value = this.get();
    let oldValue = this.value;
    this.value = value;
    if (this.user) {
      this.cb.call(this.vm, value, oldValue);
    } else {
      this.cb();
    }
  }
  update() {
    if (this.lazy) {
      this.dirty = true;
    } else {
      this.run();
      // queueWatcher(this);
    }
  }
  evaluate() {
    this.value = this.get();
    this.dirty = false;
  }
  depend() {
    let i = this.deps.length;
    // 遍历整个计算属性watcher,拿到每一个dep
    while (i--) {
      this.deps[i].depend();
    }
  }
}
let queue = []; // 将需要批量更新的watcher存放到一个队列中
let has = [];
let pending = false;
function flusWatcher() {
  queue.forEach((item) => {
    item.run();
  });
  queue = [];
  has = [];
  pending = false;
}
function queueWatcher(watcher) {
  let id = watcher.id; // 每个组件都是同一个watcher.所以这里存在一个问题就是在渲染页面的时候，读取数据的时候，不同的dep实例保存的都是同一个watcher
  if (has[id] == null) {
    queue.push(watcher);
    has[id] = true;
    if (!pending) {
      nextTick(flusWatcher); //相当于定时器，就是一个异步队列
    }
    pending = true;
  }
}
